﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Globalization;

namespace Billing
{
    /// <summary>
    /// Класс содержит общие функции и перменные, используемые в различных частях программы
    /// </summary>
    public static class Common
    {
        #region Общие констнаты

        /// <summary>
        /// Путь к файлу помощи
        /// </summary>
        public static string HELP_PATH = Path.ChangeExtension(Application.ExecutablePath, ".chm");
        
        /// <summary>
        /// Путь к файлу настроек
        /// </summary>
        public static string SETTING_PATH = Path.ChangeExtension(Application.ExecutablePath, ".ini");

        #endregion

        /// <summary>
        /// Функция записи в файл. Значение stringValue записывается в конец файла fileName
        /// </summary>
        /// <param name="stringValue">Строковое значение, которое нужно сохранить в файле fileName</param>
        /// <param name="fileName">Имя файла, в конец которого дописывается занчение stirngValue</param>
        public static void ToFile(string stringValue, string fileName)
        {
            try
            {
                using (FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    using (StreamWriter streamWriter = new StreamWriter(fileStream))
                    {
                        streamWriter.WriteLine(stringValue);
                    }
                }
            }
            catch
            {
                return;
            }
        }

        /// <summary>
        /// Вызов справки программы
        /// </summary>
        /// <param name="topic">Тема помощи</param>
        /// <param name="helpNavigator">Значение в навигаторе</param>
        public static void GetHelp(string topic, HelpNavigator helpNavigator)
        {
            try
            {
                Help.ShowHelp(null, Common.HELP_PATH, helpNavigator, topic + ".htm");
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }
        }
 
        /// <summary>
        /// Показ лог-файла приложения
        /// </summary>
        public static void ShowLog()
        {
            try
            {
                string filePath = Path.ChangeExtension(Application.ExecutablePath, ".log");
                if (!File.Exists(filePath))
                    Common.ToFile("", filePath);
                System.Diagnostics.Process.Start("notepad.exe", filePath);
            }
            catch (Exception err)
            {
                Log.ToLog(err.Message);
            }

        }

        /// <summary>
        /// Основная форма приложения
        /// </summary>
        public static FormMain FormMain { get; set; }

     }
    
    /// <summary>
    /// Класс содержит функционал для записи сообщения в лог файл.
    /// </summary>
    /// <remarks>Файл лога формируется автоматически, при создании первой записи. Файл лога располагается в директории установки программы и 
    /// имеет то же наименование, что и исполняемый файл, за исключением расширения. Расшиирение файла - .log</remarks>
    public static class Log
    {
        public static void ToLog(string data)
        {
            try
            {
                using (FileStream fileStream = new FileStream(
                        Path.ChangeExtension(Application.ExecutablePath, ".log"),
                        FileMode.Append,
                        FileAccess.Write,
                        FileShare.None))
                {
                    using (StreamWriter streamWriter = new StreamWriter(fileStream))
                    {
                        StringBuilder strBuild = new StringBuilder("");
                        if (String.IsNullOrEmpty(data))
                            strBuild.Append(" ");
                        else
                            strBuild.Append(DateTime.Now.ToString() + "\t");
                        streamWriter.WriteLine(strBuild.ToString() + data);
                    }
                }
            }
            catch
            {
                return;
            }
        }
    }
    
    /// <summary>
    /// Класс содержит функции позволяющие выполнять сериализацию нужных объектов
    /// </summary>
    public sealed class BillingSerialize
    {
        #region Публичные методы

        /// <summary>
        /// Сериализация объекта obj в файл fileName
        /// </summary>
        /// <param name="fileName">Имя файла, куда сериализуется объект obj</param>
        /// <param name="obj">Объект для сериализации в файл fileName</param>
        static public void Serialize(string fileName, object obj)
        {
            if (obj == null)
                return;
            BinaryFormatter f = new BinaryFormatter();
            using (Stream nf = NewFileStream(fileName))
            {
                f.Serialize(nf, obj);
            }
        }
        
        /// <summary>
        /// Восстановление объекта в соответствии с сохраненным состоянием из файла fileName
        /// </summary>
        /// <param name="fileName">Имя файла, откуда восстанавливается состояние объекта</param>
        /// <returns>Восстановленный объект</returns>
        /// <remarks>При использовании функции нужно знать, тип объкта для которого восстанавливается состояние. Функцию нужно использовать в блоке try catch, на случай
        /// возникновения исключительной ситуации при несовпадении типов</remarks>
        static public object Deserialize(string fileName)
        {
            BinaryFormatter f = new BinaryFormatter();
            using (Stream strm = GetFileStream(fileName))
            {
                if ((strm != null) && (strm.Length != 0))
                {
                    return f.Deserialize(strm);
                }
                else
                    return null;
            }
        }

        #endregion

        #region Приватные методы

        static private Stream NewFileStream(string fileName)
        {
            return File.Create(fileName);
        }
        static private Stream GetFileStream(string fileName)
        {
            if (File.Exists(fileName))
                return File.OpenRead(fileName);
            else
                return null;
        }
        private BillingSerialize() { }

        #endregion
    }

    /// <summary>
    /// Вызов сообщения для пользователя с поддержкой направления письма, в зависимости от настроек системы
    /// </summary>
    public static class AwareMessageBox
    {
        public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options)
        {
            if (IsRightToLeft(owner))
            {
                options |= MessageBoxOptions.RtlReading |
                MessageBoxOptions.RightAlign;
            }
            return MessageBox.Show(owner, text, caption,
            buttons, icon, defaultButton, options);
        }
        private static bool IsRightToLeft(IWin32Window owner)
        {
            Control control = owner as Control;

            if (control != null)
            {
                return control.RightToLeft == RightToLeft.Yes;
            }

            // If no parent control is available, ask the CurrentUICulture
            // if we are running under right-to-left.
            return CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft;
        }
    }

}
